#include "qlmodem/task_modem.h"
#include "comm/ota.h"
#include "flash/flash_main.h"
#include "flash/flash_if.h"
#include "misc/misc_api.h"
#include "service/include/swei_ota.h"
#include "service/include/swei_cmd.h"
#include "service/include/swei_status.h"
#include "service/include/swei_downlink.h"
#include "mmgr/include/mmgr_pdp.h"
#include "misc/misc_system.h"

static int tbox_ota_erase(void);
static ssize_t tbox_ota_write(const void *buf, size_t len);
static DLCMD_RET_TYPE_ENUM tbox_ota_handler(DOWN_LINK_CMD_ENUM cmd_id, uint16_t cmd_opcode, const unsigned char * p_data, uint32_t data_len);

static struct file_download file_download_info = {
    .erase = tbox_ota_erase,
    .write = tbox_ota_write,
    .writable_size = 0,
    .file_type = NO_ENC_FILE,
    .connect_timeout = 5,
    .download_timeout = 10,
    .ver_verify = NULL,
    .auth_gen = NULL,
    .user_agent = NULL,
};

typedef struct {
    int ota_received;
    int ota_id;
    int total_len;
    bool is_ota;
} ota_info_t;

static ota_info_t ota_info = {
    .ota_received = 0,
    .ota_id = -1,
    .is_ota = false,
    };


bool is_tbox_ota(void)
{
    return ota_info.is_ota;
}


static int tbox_ota_erase(void)
{
    return aad_flash_zone_clear(FILE_OTA_ID, AADL_WAIT | AADL_KEEP_OUTSIDE , 0);
}
    

void swei_ota_init(void) 
{
    swei_downlink_cmd_register(DOWN_LINK_CMD_OTA_TBOX, tbox_ota_handler);
    swei_downlink_cmd_register(DOWN_LINK_CMD_OTA_BLE_TBOX, tbox_ota_handler);
    swei_downlink_cmd_register(DOWN_LINK_CMD_OTA_ELEC_CON, tbox_ota_handler);
    swei_downlink_cmd_register(DOWN_LINK_CMD_OTA_BMS, tbox_ota_handler);
    swei_downlink_cmd_register(DOWN_LINK_CMD_OTA_DIS, tbox_ota_handler);
}

#if 0
uint32_t sum = 0;
#include "flash/flash_main.h"
static int tbox_ota_receive(int index, const void *buf, size_t cnt, unsigned int length)
{
    static uint64_t ota_received = 0;
    int res = 0;

    if (true == ota_info.is_exist_ota)
        return -EPERM; 

    //若写入flash的内容与固件缓存对不上，取消升级
    res = app_flash_write((uint64_t)ota_received, cnt, (unsigned char *)buf);
    if (res != 0) {
        ota_info.is_exist_ota = true;
        return -ENOENT;
    }
    ota_received += cnt;

    if (ota_received >= length) {
        //若写入flash的内容与固件缓存对不上，取消升级
        res = app_flash_flush();  
        if (0 != res) {
            ota_info.is_exist_ota = true;
            return -ENOENT;
        }

        //写入升级标志位失败，退出升级
        char bootinfo_str[16] = "REDY";
        res = aad_flash_direct_write(FILE_OTA_FLAG_ID, 0, bootinfo_str, strlen(bootinfo_str), AADL_WAIT | AADL_KEEP_OUTSIDE , 0);
        if (res != 0) {
            ota_info.is_exist_ota = true;
            log_i("Fail to set ota flag id, reason: %d", res);
            return res;
        }            
        
        tbox_system_reboot(1000);
    }

    return res;
}
#endif


static DLCMD_RET_TYPE_ENUM tbox_ota_handler(DOWN_LINK_CMD_ENUM cmd_id, uint16_t cmd_opcode, const unsigned char * p_data, uint32_t data_len)
{
    int res = 0;
    int retry = 2;

    if (p_data == NULL)
        return DLCMD_RET_ERROR;

    /* 只有开机状态下能升级 */
    if (WORK_MODE_NORMAL != misc_get_work_mode())
        return DLCMD_RET_ERROR;
    
    /* 清空url缓存 */
    memset(file_download_info.url, 0, sizeof(file_download_info.url));

    /* pdp连接成功 */
    if (mmgr_pdp_status_get() == true \
        &&ota_info.is_ota == false) {

        /* 为避免失败，尝试两次 */
        for (int i = 0; i < retry; i++) {
            #if 0 
            res = qltask_modem_https_start(&https_ota_info);
            #else
            /* 前15字节为md5校验码 */
            memset(file_download_info.url, 0, data_len - 16);
            memcpy(file_download_info.url, p_data + 16, data_len - 16);

            res = qltask_modem_file_download_start(&file_download_info);
            #endif
            if (0 == res) {
                ota_info.is_ota = true;
                ota_info.ota_id = cmd_id;
                break;                
            }
        }
        
        if (0 != res) {
            log_e("Fail to start ota, res: %d", res);
            return DLCMD_RET_ERROR;
        }
    }
    return DLCMD_RET_CONTINUE;
}


static void ota_info_recover(void)
{
        ota_info.is_ota = false;
        ota_info.ota_id = -1;
        ota_info.ota_received = 0;
        ota_info.total_len = 0;    
}

static ssize_t tbox_ota_write(const void *buf, size_t len)
{
    int ret = 0;

    if (buf == NULL)
        return -EINVAL;
    
    /* 在这里禁止调度来避免flash写入错误 */
    ret = app_flash_write(ota_info.ota_received, len, (unsigned char*)buf);

    if (ret != 0)
    {
        log_e("Fail to save iot firmware into flash! id:%d,ret:%d\r\n", FILE_OTA_FLAG_ID, ret);
        return ret;
    }    

    ota_info.ota_received += len;
    
    if (ota_info.total_len == 0)
        qltask_modem_file_download_progress_get(&ota_info.total_len, NULL);

    if (ota_info.total_len > 0
        && ota_info.ota_received >= ota_info.total_len) {
        swei_netProtocol_ack_downlink_cmd(ota_info.ota_id, CMD_SUCCESS, true);
        
        /* 将剩余的固件缓存直接写入flash */
        app_flash_flush();
        
        if (ota_info.ota_id == DOWN_LINK_CMD_OTA_TBOX) {
            //写入升级标志位失败，退出升级
            char bootinfo_str[16] = "REDY";
            ret = aad_flash_direct_write(FILE_OTA_FLAG_ID, 0, (const uint8_t *)bootinfo_str, 
                                            strlen(bootinfo_str), AADL_WAIT | AADL_KEEP_OUTSIDE , 0);
            if (ret != 0) {
                ota_info_recover();
                log_i("Fail to set ota flag id, reason: %d", ret);
                return ret;
            }              
            
            tbox_system_reboot(1000);
        } else if (ota_info.ota_id == DOWN_LINK_CMD_OTA_DIS) {
            iot_upgrade_request(type_dis, ota_info.total_len, 1, 4096);
        } else if (ota_info.ota_id == DOWN_LINK_CMD_OTA_ELEC_CON) {
            iot_upgrade_request(type_ecu, ota_info.total_len, 1, 4096);
        } else if (ota_info.ota_id == DOWN_LINK_CMD_OTA_BMS) {
            iot_upgrade_request(type_bms, ota_info.total_len, 1, 4096);
        } else if (ota_info.ota_id == DOWN_LINK_CMD_OTA_BLE_TBOX) {
            iot_upgrade_request(type_ble, ota_info.total_len, 1, 4096);            
        }

        ota_info_recover();
    }

    return len;
}


/**
 * @brief 定期检查ota
 */
void swei_ota_rtc_check(void)
{
    // //.1.检查是否有需要OTA进行升级的信息
    // struct FW_BAT_INFO_STRU   bat_info={0.0f, 0.0f, 0.0f};
    // fw_power_stat_e_type      power_mode;
    // int ret = 0;
    // ret = fw_get_supply_power_status(&power_mode);
    // if ((ret == -1))
    // {
    //     log_e("get power mode return error, res:%d", ret);
    // }
    // if (FW_BAT_POWER==power_mode)
    // {
    //     fw_bat_get_status(&bat_info);
    // }
    // else if (FW_MAIN_POWER==power_mode)
    // {
    //     log_i("power in main power mode");
    // }
    // if (battery_status.charg_stat == IN_CHARGING) // 充电时不允许升级
    // {        
    //      return;
    // }
    // if((bat_info.volt > 3.6f)||(FW_MAIN_POWER==power_mode))//考虑未激活升级，直接使用主电池进行升级;
    // {
    //     tbox_ota_deal_tar_file();
    //     ret = tbox_ota_is_flag_file_exist() || tbox_ota_is_fota_pack_exist() || tbox_ota_is_mcu_update_bin_exist();
    //     if(TRUE == ret)
    //     {
    //         log_i(" tbox ota file exists. Prepare to ota!!!!!!!!!!!!!!!");
    //         /************* 升级mcu文件 **********/
    //         if (0 != swei_mcu_check_ver_and_update())
    //         {
    //             log_e("swei_mcu_check_ver_and_update fail or not need update");
    //         }
    //         /*************FOTA的包存在，FOTA的升级流程***************/
    //         if(TRUE==tbox_ota_is_fota_pack_exist())
    //         {
    //             tbox_fota_pro();
    //             return;/*******FOTA升级与TBOX升级独立，直接return***********/
    //         }
    //         if(TRUE==tbox_ota_is_flag_file_exist())
    //         {
    //             tbox_app_ota_pro();
    //             return;
    //         }
    //     }
    //     else
    //     {
    //         log_i("ota flag file not exist!!!!!!!!!!!!!!!");

    //         // 获取mcu的版本
    //         swei_mcu_get_version_first(); // 第一次获取mcu的版本，不为空则不获取
    //     }
    // }
    // else
    // {
    //     log_i("tbox bat val less than 3.6v or not in main power, wait next ota check");
    // } 

    // // 上传 mcu 版本
    // if (false == swei_mcu_get_mcu_upload_flag())
    // {
    //     char ver[MCU_VER_LEN] = "";
    //     swei_mcu_get_mcu_ver(ver, MCU_VER_LEN);
    //     if (0 != ver[0])
    //     {
    //         //上传数据
    //         log_i("upload mcu ver");
    //         if (0 == swei_netProtocol_send_tbox_dev_ver_msg(EN_TBOX_VERSION_INFO_UPLOAD_MCU))
    //         {
    //             swei_mcu_set_mcu_upload_flag(true);
    //         }
    //     }
    // }
}